<script lang="ts" setup>
import type { RoleInOrUpReq, SysRoleVO } from '@/api/role/roleType'
import { deleteRole, getRolePage, getRolePermission, saveRole, updateRolePermission } from '@/api/role/roleApi'
import useLayoutStore from '@/store/modules/setting'
import { ElMessage } from 'element-plus'
import { nextTick, onMounted, ref } from 'vue'

// 定义当前页码
const currentPage = ref<number>(1)
// 默认页行数
const pageSize = ref<number>(10)
// 数据总数
const total = ref<number>(0)
// 定义响应式数据 roleName 收集角色名
const roleName = ref<string>('')
// 定义响应式数组 roles 收集所有角色数据
const roleList = ref<SysRoleVO[]>([])
// 使用layout组件小仓库
const layoutStore = useLayoutStore()
// 定义响应式数据控制 角色信息对话框
const roleDialog = ref<boolean>(false)
// 定义响应式数据收集 roleDialog 中角色名的数据
const roleInOrUpReq = ref<RoleInOrUpReq>({
  roleName: '',
})
// 获取 form 组件实例
const operateRoleFormRef = ref()
// 定义响应式数据控制角色权限分配抽屉展示
const roleDrawer = ref<boolean>(false)
// 定义响应式数据收集 角色权限树 数据
const roleAuthorityData = ref<any[]>([])
// 定义 角色权限树 的 roleAuthorityProps
const roleAuthorityProps = ref({
  children: 'children',
  label: 'name',
})
// 定义一个数组存储当前角色权限树选中的节点数据
const roleAuthorityChecked = ref<number[]>([])
// 定义响应式数据收集 角色权限树 当前的角色 id
const roleId = ref<number>(0)
// 获取 角色权限树 组件实例
const roleAuthorityTreeRef = ref<any>()

/**
 * 默认分页查询
 * 当前第一页
 * 每页10条数据
 */
onMounted(() => {
  // 设置当前页码为1
  currentPage.value = 1
  // 设置每页数据条数10
  pageSize.value = 10
  // 设置 roleName 为空
  roleName.value = ''
  getRolePageData()
})

/**
 * 根据收集到的表单数据分页查询角色列表
 */
async function getRolePageData() {
  const result: any = await getRolePage({
    roleName: roleName.value,
    pageReq: {
      current: currentPage.value,
      size: pageSize.value,
    },
  })
  if (result.success) {
    // 设置表格数据
    roleList.value = result.data
    // 设置总记录数
    total.value = result.total
  }
}

// 重置界面
function reset() {
  layoutStore.refresh = !layoutStore.refresh
}

// 分页器下拉菜单自定义事件
function handerPageData() {
  getRolePageData()
}

// 添加角色按钮事件
function addRole() {
  roleDialog.value = true
  // 清空数据
  Object.assign(roleInOrUpReq.value, {
    roleName: '',
    id: 0,
  })
  // 清空上一次表单校验结果
  nextTick(() => {
    operateRoleFormRef.value.clearValidate('roleName')
  })
}

// 修改角色按钮事件
function updateRole(row: SysRoleVO) {
  roleDialog.value = true

  // 将当前行数据填入角色对话框中
  Object.assign(roleInOrUpReq.value, {
    id: row.id,
    roleName: row.roleName,
  })
}

// 角色对话框表单校验规则
const roleFormRule = ref({
  roleName: [
    {
      required: true,
      message: '请输入角色名',
      trigger: 'blur',
    },
  ],
})

// 保存角色信息对话框表单数据
async function onSaveRoles() {
  // 先执行表单校验成功才能执行后续保存操作
  await operateRoleFormRef.value.validate()
  const result: any = await saveRole(roleInOrUpReq.value)
  if (result.success) {
    // 打印操作成功日志
    ElMessage({
      message: '操作成功',
      type: 'success',
    })
    roleDialog.value = false
    // 设置当前页码为1
    currentPage.value = 1
    // 设置每页数据条数10
    pageSize.value = 10
    // 设置 roleName 为空
    roleName.value = ''
    getRolePageData()
  }
}

// 分配权限按钮事件
async function setPermission(row: SysRoleVO) {
  // 打开抽屉
  roleDrawer.value = true
  // 清空角色权限树选中的节点数据
  roleId.value = row.id as number
  roleAuthorityChecked.value = []
  // 获取当前行角色id的权限树数据
  const result: any = await getRolePermission({
    id: row.id as number,
  })
  if (result.success) {
    // 获取当前行角色id的权限树数据
    roleAuthorityData.value = result.data
    // 设置当前角色权限树选中的节点数据
    roleAuthorityChecked.value = getRoleAuthorityChecked(roleAuthorityData.value, [])
  }
}

// 递归收集 当前角色权限树选中的节点数据
function getRoleAuthorityChecked(data: any[], initArr: number[]) {
  data.forEach((item) => {
    // 添加当前角色权限树选中的节点数据
    if (item.select && item.type === 1) {
      initArr.push(item.id)
    }
    // 递归收集 当前角色权限树选中的节点数据
    if (item.children && item.children.length > 0) {
      getRoleAuthorityChecked(item.children, initArr)
    }
  })
  return initArr
}

// 更新角色权限确定事件
async function onSaveRoleAuthority() {
  const result: any = await updateRolePermission({
    id: roleId.value,
    authorityIds: roleAuthorityTreeRef.value.getCheckedKeys().concat(roleAuthorityTreeRef.value.getHalfCheckedKeys()),
  })
  if (result.success) {
    if (result.data) {
      // 打印操作成功日志
      ElMessage({
        message: '操作成功',
        type: 'success',
      })
      // 关闭 分配权限抽屉
      roleDrawer.value = false
      // 设置当前页码为1
      currentPage.value = 1
      // 设置每页数据条数10
      pageSize.value = 10
      // 设置 roleName 为空
      roleName.value = ''
      getRolePageData()
    }
    else {
      ElMessage({
        message: '操作失败',
        type: 'error',
      })
    }
  }
}

// 删除角色按钮事件
async function onDeleteRole(row: SysRoleVO) {
  const result: any = await deleteRole({ ids: [row.id as number] })
  if (result.success && result.code === 200) {
    // 打印操作成功日志
    ElMessage({
      message: '操作成功',
      type: 'success',
    })
    // 设置当前页码为1
    currentPage.value = 1
    // 设置每页数据条数10
    pageSize.value = 10
    // 设置 roleName 为空
    roleName.value = ''
    getRolePageData()
  }
  else {
    ElMessage({
      message: `删除失败,失败原因：${result.message}`,
      type: 'error',
    })
  }
}
</script>

<template>
  <!-- 查询条件 -->
  <el-card style="height: 75px;">
    <el-form :inline="true" class="form-inline">
      <el-form-item label="角色名">
        <el-input v-model="roleName" placeholder="请输入角色名" />
      </el-form-item>
      <el-form-item>
        <el-button v-hasButton="`btn.role.page`" type="primary" icon="Search" @click="getRolePageData">
          查询
        </el-button>
        <el-button v-hasButton="`btn.role.page`" icon="Refresh" @click="reset">
          重置
        </el-button>
      </el-form-item>
    </el-form>
  </el-card>

  <!-- 查询结果列表 -->
  <el-card style="margin: 10px 0px;">
    <el-button v-hasButton="`btn.role.save`" type="primary" icon="Plus" @click="addRole">
      添加角色
    </el-button>
    <el-table style="margin: 10px 0px;" :border="true" :data="roleList">
      <el-table-column type="selection" align="center" width="50px" />
      <el-table-column type="index" label="#" align="center" width="50px" />
      <el-table-column prop="id" label="ID" align="center" />
      <el-table-column prop="roleName" label="角色名" align="center" />
      <el-table-column prop="createTime" label="创建时间" align="center" />
      <el-table-column prop="creatorName" label="创建人" align="center" />
      <el-table-column prop="modifyTime" label="修改时间" align="center" />
      <el-table-column prop="modifierName" label="修改人" align="center" />
      <el-table-column label="操作" width="350px" align="center">
        <template #default="scope">
          <el-button v-hasButton="`btn.role.queryRoleAuthority`" type="primary" icon="Pointer" @click="setPermission(scope.row)">
            分配权限
          </el-button>
          <el-button v-hasButton="`btn.role.save`" type="primary" icon="EditPen" @click="updateRole(scope.row)">
            修改
          </el-button>
          <el-popconfirm :title="`确定删除${scope.row.roleName}吗？`" @confirm="onDeleteRole(scope.row)">
            <template #reference>
              <el-button v-hasButton="`btn.role.delete`" type="danger" icon="Delete">
                删除
              </el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页器 -->
    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="[10, 20, 30, 40, 50]"
      layout="prev, pager, next, jumper,->, sizes, total"
      :total="total"
      @current-change="getRolePageData"
      @size-change="handerPageData"
    />
  </el-card>

  <!-- 角色信息对话框：完成添加新的角色或者更新已有的角色信息 -->
  <el-dialog v-model="roleDialog" :title="roleInOrUpReq.id ? '修改角色' : '添加角色'">
    <el-form ref="operateRoleFormRef" :model="roleInOrUpReq" :rules="roleFormRule">
      <el-form-item label="角色名" prop="roleName">
        <el-input v-model="roleInOrUpReq.roleName" placeholder="请输入角色名" />
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="roleDialog = false">
          取消
        </el-button>
        <el-button v-hasButton="`btn.role.save`" type="primary" @click="onSaveRoles">
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>

  <!-- 分配角色权限抽屉 -->
  <el-drawer v-model="roleDrawer" title="分配角色权限">
    <template #header>
      <h4>分配角色权限</h4>
    </template>
    <template #default>
      <!-- 菜单/按钮数据树 -->
      <el-tree
        ref="roleAuthorityTreeRef"
        style="max-width: 600px"
        :data="roleAuthorityData"
        show-checkbox
        node-key="id"
        default-expand-all
        :props="roleAuthorityProps"
        :default-checked-keys="roleAuthorityChecked"
      />
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button @click="roleDrawer = false">
          取消
        </el-button>
        <el-button v-hasButton="`btn.role.updateRoleAuthority`" type="primary" @click="onSaveRoleAuthority">
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<style scoped>
.form-inline {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
